﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Bouyei.Algo.Graph
{
    public class AStarAlgorithm
    {
        public AStarNode[,] Graphic { get; private set; }
        public AStarNode Start { get; private set; }

        public AStarNode End { get; private set; }

        private List<AStarNode> OPEN=null;
        private List<AStarNode> CLOSE=null;

        public AStarAlgorithm(AStarNode[,] graphic, AStarNode start, AStarNode end)
        {
            this.Graphic = graphic;
            this.Start = start;
            this.End = end;

            OPEN = new List<AStarNode>();
            CLOSE = new List<AStarNode>();

            OPEN.Add(start);
        }

        public void Execute()
        {
            while (OPEN.Count > 0)
            {
                var best = GetBestFromOpen();
                if (best == null) break;

                if (best.CompareTo(End) == 0)
                    break;
            }
        }

        private AStarNode GetBestFromOpen()
        {
            if (OPEN.Count == 0) return null;
            else if (OPEN.Count == 1) return OPEN[0];
            else
            {
                AStarNode node = OPEN[0];
                for(int i=1;i<OPEN.Count;++i)
                {
                    if(node.CompareTo(OPEN[i])>0)
                    {
                        node = OPEN[i];
                    }
                }
                return node;
            }
        }
    }

    public class AStarNode:IComparable<AStarNode>
    {
        public int X { get; set; }//坐标x

        public int Y { get; set; }//坐标y

        public int G { get; set; }//当前点到七点距离

        public int H { get; set; }//当前点到终点距离

        public int F { get; set; }//总距离

        public AStarNode ParentNode { get; set; }//父节点

        /// <summary>
        /// F值比较
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public int CompareTo(AStarNode node)
        {
            if (this.F < node.F) return -1;
            else if (this.F > node.F) return 1;
            else return 0;
        }

        public int HValue(AStarNode end)
        {
            return (Math.Abs(end.X - this.X) + Math.Abs(end.Y - this.Y)) * 10;
        }
    }
}
